﻿using HelloMods.Healths;
using Modding;
using System.Collections;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;

namespace HelloMods
{
    public partial class PlayerScript : MonoBehaviour
    {
        internal static PlayerScript instance = null;
        private Modding.ILogger logger = null;
        private SettingsPanel settingsPanel;
        private Settings settings = Settings.Instance;

        private HealthPoint healthPoint;

        // Use this for initialization
        void Start()
        {
            this.logger = HelloMod.LoadedInstance;

            install();
        }

        void install()
        {

            this.settingsPanel = this.gameObject.AddComponent<SettingsPanel>();
            this.healthPoint = this.gameObject.AddComponent<HealthPoint>();

            ModHooks.OnEnableEnemyHook += ModHooks_OnEnableEnemyHook;
            ModHooks.HitInstanceHook += ModHooks_HitInstanceHook;
            ModHooks.TakeDamageHook += ModHooks_TakeDamageHook;
            ModHooks.TakeHealthHook += ModHooks_TakeHealthHook;
            ModHooks.SetPlayerIntHook += ModHooks_SetPlayerIntHook;
            ModHooks.HeroUpdateHook += ModHooks_HeroUpdateHook;
            ModHooks.AttackHook += ModHooks_AttackHook;
            ModHooks.BeforeSavegameSaveHook += ModHooks_BeforeSavegameSaveHook;
        }

        private void ModHooks_BeforeSavegameSaveHook(SaveGameData obj)
        {
            obj.playerData.gotCharm_23 = true;
            obj.playerData.gotCharm_24 = true;
            obj.playerData.gotCharm_25 = true;
        }


        private void ModHooks_AttackHook(GlobalEnums.AttackDirection dir)
        {
            var s = settings;
            if (!settings.Enabled)
                s = new Settings();

            var player = GameObject.FindGameObjectWithTag("Player");
            var hero = player.GetComponent<HeroController>();

            var slash = hero.GetType().GetField("slashComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(hero) as NailSlash;
            if (slash)
            {
                if (dir == GlobalEnums.AttackDirection.normal)
                    slash.scale = new Vector3(s.NailScale, 1, 1);
                else
                    slash.scale = new Vector3(1, s.NailScale, 1);
            }
        }

        float origin_jump_speed = 0;
        private void ModHooks_HeroUpdateHook()
        {
            var player = GameObject.FindGameObjectWithTag("Player");
            var hero = player.GetComponent<HeroController>();
            var rigid = player.GetComponent<Rigidbody2D>();
            var inputHandler = GameManager.instance.GetComponent<InputHandler>();

            if (!hero)
            {
                return;
            }
            var s = settings;
            if (!settings.Enabled)
                s = new Settings();
            if (origin_jump_speed == 0f)
            {
                origin_jump_speed = hero.JUMP_SPEED;
                //    logger.Log($"origin_jump_speed={origin_jump_speed},{inputHandler},{rigid}");
            }


            if (GameManager.instance.gameState == GlobalEnums.GameState.PLAYING && rigid && inputHandler && s.InfinityJump)
            {
                if (inputHandler.inputActions.jump.IsPressed && rigid.velocity.y != 0.0f)
                    rigid.velocity = Vector2.up * hero.JUMP_SPEED;
            }

            if (s.InfinityMP)
                hero.AddMPCharge(30);
        }

        private int ModHooks_SetPlayerIntHook(string name, int orig)
        {
            if (name == "geo")
            {
                var old = PlayerData.instance.GetVariableInternal<int>(name);
                if (old < orig)
                    return old + Mathf.FloorToInt((orig - old) * settings.AddGeo);

                return orig;
            }
            return orig;
        }



        void OnDestroy()
        {
            logger.Log($"OnDestroy");
            ModHooks.OnEnableEnemyHook -= ModHooks_OnEnableEnemyHook;
            ModHooks.HitInstanceHook -= ModHooks_HitInstanceHook;
            ModHooks.TakeDamageHook -= ModHooks_TakeDamageHook;
            ModHooks.TakeHealthHook -= ModHooks_TakeHealthHook;
            ModHooks.SetPlayerIntHook -= ModHooks_SetPlayerIntHook;
            ModHooks.HeroUpdateHook -= ModHooks_HeroUpdateHook;
            ModHooks.AttackHook -= ModHooks_AttackHook;
            ModHooks.BeforeSavegameSaveHook -= ModHooks_BeforeSavegameSaveHook;
            if (this.settingsPanel)
            {
                GameObject.Destroy(settingsPanel);
                this.settingsPanel = null;
            }
            if (this.healthPoint)
            {
                GameObject.Destroy(healthPoint);
                this.healthPoint = null;
            }
        }

        public void Update()
        {

        }

        private HitInstance ModHooks_HitInstanceHook(HutongGames.PlayMaker.Fsm owner, HitInstance hit)
        {
            var scale = settings.Enabled ? settings.Attack : 1.0f;
            hit.DamageDealt = (int)(hit.DamageDealt * scale);
            return hit;
        }

        private bool ModHooks_OnEnableEnemyHook(GameObject enemy, bool isAlreadyDead)
        {
            var health = enemy.GetComponent<HealthManager>();
            healthPoint.AddEnemy(enemy, health);
            return isAlreadyDead;
        }

        private int ModHooks_TakeHealthHook(int damage)
        {
            var scale = settings.Enabled ? settings.TakeHealth : 1.0f;
            return (int)(damage * scale);
        }

        private int ModHooks_TakeDamageHook(ref int hazardType, int damage)
        {
            var scale = settings.Enabled ? settings.TakeDamage : 1.0f;
            return (int)(damage * scale);

        }


    }
}